package valid

import (
	"strings"

	"gitee.com/gousing/helper/valid/chinese_id"
)

// 验证电子邮箱，通过ASCII快速检查再通过正则，比纯正则性能提高50%
//   - localPart 允许大小写字母数字，允许连字符".-_" (限制为不允许连字符开头及结尾，不允许连续多个，仅允许出现在字符串中间)
//   - domainPart 允许大小写字母数字，允许连字符".-" (限制为不允许连字符开头及结尾，不允许连续多个，仅允许出现在字符串中间)
func IsEmail(v string) bool {
	if len(v) < 5 {
		// 最短的邮箱号 1@1.c
		return false
	}
	l := len(v)
	// 必须且仅有一个 @ 符号
	atIndex := -1
	for i := range l {
		if v[i] == '@' {
			if atIndex != -1 {
				return false
			}
			atIndex = i
		}
	}
	if atIndex < 1 || atIndex+1 > l-3 {
		return false
	}
	localPart := v[:atIndex]    // 至少1个字符
	domainPart := v[atIndex+1:] // 至少3个字符
	// IsLetterWith 字符串是否为纯字母、数字
	//   - val 字符串
	//   - alpha 0 允许大小写 1 进允许小写 2 仅允许大写
	//   - number 0 不允许数字 1 允许数字(任意位置) 2允许数字（限制为不允许数字开头）
	//   - length 字符串长度 0/不限制
	//   - symbols 字符串中允许的使用的其他ASCII字符符号，如_-连字符（限制为不允许连字符开头及结尾，不允许连续多个，仅允许出现在字符串中间）
	if !IsLetterWith(localPart, 0, 1, 0, "-._") ||
		!IsLetterWith(domainPart, 0, 1, 0, "-.") {
		// 含有非法字符
		return false
	}
	// 至少含有一个 .构成域名
	return strings.Contains(domainPart, ".")
}

// IsChineseMobile 无正则验证11位手机号是否正确，ASCII快速检查
//   - 移动号段：134 135 136 137 138 139 147 148 150 151 152 157 158 159 172 178 182 183 184 187 188 195 198
//   - 联通号段：130 131 132 145 146 155 156 166 167 171 175 176 185 186 196
//   - 电信号段：133 149 153 173 174 177 180 181 189 190 191 193 199
//   - 广电号段：192
//   - 虚拟运营商:162 165 167 170 171
func IsChineseMobile(v string) bool {
	l := len(v)
	// 去掉86前缀
	if l > 11 {
		if v[0:4] == "+86-" || v[0:4] == "+86." || v[0:4] == "+86 " || v[0:4] == "0086" {
			v = v[4:]
			l = len(v)
		} else if v[0:3] == "+86" || v[0:3] == "86-" || v[0:3] == "86." || v[0:3] == "86 " {
			v = v[3:]
			l = len(v)
		} else {
			return false
		}
	}
	// 中国手机号码必须是11位
	if l != 11 {
		return false
	}
	// 中国手机号码第1位必须是1, 必须全是数字, 第2位只能是 3-9
	if v[0] != '1' || !IsUint(v) || v[1] < '3' {
		return false
	}
	return true
}

// IsChineseID 验证中国身份证号码
func IsChineseID(no string) bool {
	return chinese_id.IsValid(no)
}

// ChineseIDParse 解析中国身份证号码信息
//   - birthday "2006/01/02"
//   - isMale true:男, false:女
//   - addrMask 0:北京, 1:天津, 2:河北, 3:山西...
//   - err error
func ChineseIDParse(no string) (birthday string, isMale bool, addrMask int, err error) {
	return chinese_id.ParseInfo(no)
}
